const { db } = require('../db');
const redis = require('../db/redis')
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const moment = require('moment');
const { OPENAI_API_KEY, EXPIRES_IN, ZHI_ZENGZENG_KEY } = require('../config');
const nodemailer = require('nodemailer');
const https = require('https');
const { Configuration, OpenAIApi } = require('openai');
const pump = require('pump');
const { PassThrough, Readable, Transform } = require('stream');
const axios = require('axios');
const { createProxyMiddleware } = require('http-proxy-middleware');
const { logger } = require('../utils/serviceLogger');

const confg = new Configuration({
    apiKey: `Bearer ${OPENAI_API_KEY}`
});
const openai = new OpenAIApi(confg);


exports.normalChat = async (req, res) => {
    let { questionContent } = req.body;
    const restrictContent = '限制：请注意，您的回答中不要包含OpenAI、ChatGPT、gpt等字眼（不区分大小写）。问题中如果含有这些字或词，或者问你是不是chatgpt、openai（不区分大小写）等，你的回答都是否定的，即答案中含有"不是"，"No"等否定词。不区分问题的语言。\
    我的问题是：';
    const handleContent = restrictContent + questionContent;
    logger.info(req, {
        label: '小程序端开始请求',
    });
    axios.post('https://flag.smarttrot.com/v1/chat/completions', {
        model: 'gpt-3.5-turbo',
        messages: [{
            role: 'user',
            content: handleContent,
        }],
        temperature: 0.5,
        max_tokens: 2000,
    }, {
        headers: {
            'Authorization': `Bearer ${ZHI_ZENGZENG_KEY}`,
            'Content-Type': 'application/json'
        }
    }).then(axiosRes => {
        console.log('axiosRes:::', axiosRes.data);
        logger.info({}, {
            label: '小程序端结束请求，出参为：' + JSON.stringify(axiosRes.data),
        });
        if (axiosRes.status === 200) {
            const realRes = axiosRes.data;
            if (realRes.choices && realRes.choices.length > 0) {
                return res.send({
                    code: 200,
                    msg: 'success',
                    data: {
                        message: realRes.choices[0].message.content,
                        created: realRes.created
                    }
                })
            } else {
                return res.send({
                    code: 500,
                    msg: 'fail',
                    data: {
                        message: realRes.error ? realRes.error.message : '发生未知错误，请稍后重试',
                        created: new Date().getTime
                    }
                })
            }

        } else {
            return res.send({
                code: axiosRes.status,
                msg: 'fail',
                data: {
                    message: axiosRes.statusText || '发生未知错误，请稍后重试',
                    created: new Date().getTime
                }
            })
        }
    });
}

/**
 * 这个是给web端 流式输出的
 * @param {} req 
 * @param {*} res 
 * @returns 
 */
exports.proxyChat = async (req, res) => {
    console.log('来了吗')
    logger.info(req, {
        label: '开始代理请求openai的接口',
    });
    const email = req.auth.email;
    logger.info({}, {
        label: '开始减少次数，用户名为：' + email,
    });
    const res2 = await handleSubProbleCount(email);
    logger.info({}, {
        label: '结束减少次数，结果为：' + JSON.stringify(res2),
    });
    if (res2.status == 200) {
        const { messages } = req.body;
        try {
            const params = {
                model: 'gpt-3.5-turbo',
                messages: messages.map(({ role, content }) => ({ role, content })),
                temperature: 0.5,
                max_tokens: 2000,
                stream: true,
            }
            logger.info({}, {
                label: '请求openai的入参为：' + JSON.stringify(params),
            });
            axios.post('https://flag.smarttrot.com/v1/chat/completions', params, {
                headers: {
                    'Authorization': `Bearer ${ZHI_ZENGZENG_KEY}`,
                    'Content-Type': 'application/json'
                },
                responseType: 'stream'
            }).then(axiosRes => {
                console.log('axios666666:', axiosRes);
                // logger.info({}, {
                //     label: '请求openai的出参为：' + JSON.stringify(axiosRes.data),
                // });
                if (!axiosRes || axiosRes == undefined) {
                    return res.send({
                        status: 500,
                        msg: '服务器异常，请稍后再试'
                    });
                }
                res.set({
                    'Content-Type': 'text/event-stream',
                    'Transfer-Encoding': 'chunked'
                });

                res.writeHead(200, {
                    'Cache-Control': 'no-cache',
                    Connection: 'keep-alive',
                    'Content-Type': 'text/event-stream',
                    'Transfer-Encoding': 'chunked'
                })

                console.log('axiosRes', axiosRes);

                axiosRes.data.pipe(res);

            }).catch((err) => {
                logger.info({}, {
                    label: 'axios调用openai的接口失败了：' + err,
                });
            });
        } catch (err) {
            logger.info({}, {
                label: 'try catch错误了' + JSON.stringify(err),
            });
        }
    } else {
        return res.send({
            status: 500,
            msg: res2.msg || '服务器异常，请稍后再试'
        });
    }
}


exports.chat = async (req, res) => {
    const email = req.auth.email;
    const res2 = await handleSubProbleCount(email);
    if (res2.status == 200) {
        // 处理openai的api，直接去请求
        try {
            const { messages } = req.body;
            const chatGPTStream = api.createChatStream({
                model: 'gpt-3.5-turbo',
                messages: messages.map(({ role, content }) => ({ role, content })),
                temperature: 0.9,
                max_tokens: 2000,
            });

            res.setHeaders({
                'Content-Type': 'text/plain'
            });

            pump(chatGPTStream, res, (error) => {
                if (error) {
                    return res.send({
                        status: 500,
                        msg: error.message,
                        error: error.message
                    });
                } else {
                    return res.send({
                        status: 200,
                        msg: 'success',
                        data: res
                    })
                }
            });
            return res.send({
                status: 200,
                msg: 'success',
                data: res
            })
        } catch (error) {
            return res.send({
                status: 500,
                msg: 'Internal Server Erroraa',
                error: error
            });
        }
    } else {
        return res.send(res2);
    }
}

const handleSubProbleCount = async (email) => {
    const results = await queryCountByEmail(email);
    if (results.length == 1) {
        const result = JSON.stringify(results[0]);
        const jsonObj = JSON.parse(result);
        const updateTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
        if (jsonObj.can_problem_count > 0) {
            const sql = "update users set can_problem_count=?, update_time=? where email=?";
            return new Promise((resolve, reject) => {
                db.query(sql, [jsonObj.can_problem_count - 1, updateTime, email], (err, results) => {
                    if (err) {
                        resolve({
                            status: 500,
                            msg: err.message,
                            error: err.message
                        });
                    } else {
                        resolve({
                            status: 200,
                            msg: '更新成功',
                            data: {
                                count: jsonObj.can_problem_count - 1
                            }
                        });
                    }
                });
            });
        } else {
            return {
                status: 500,
                msg: '次数用完了，请至个人中心观看广告，获取次数',
                error: '次数用完了，请至个人中心观看广告，获取次数'
            };
        }
    } else {
        return {
            status: 500,
            msg: '更新失败',
            error: 'Internal Server Error'
        };
    }
}

const queryCountByEmail = async (email) => {
    const sql = "select can_problem_count, total_problem_count from users where email=?";
    return new Promise((resolve, reject) => {
        db.query(sql, email, (err, results) => {
            if (err) {
                reject(err);
            } else {
                resolve(results);
            }
        })
    })
}